﻿using Sensor.UI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;

namespace Sensor.UI.PointClouds;

public static class PointCloudFactory
{
    /// <summary>
    /// 创建分布区域模型
    /// </summary>
    /// <param name="a">椭球长半轴</param>
    /// <param name="b">椭球中半轴</param>
    /// <param name="c">椭球短半轴</param>
    /// <param name="verticalRings">垂直环数</param>
    /// <param name="horizontalRings">水平环数</param>
    /// <param name="distanceThreshold">点分配到区域的距离阈值，如果小于等于0则自动计算</param>
    /// <returns>包含分布区域的模型信息</returns>
    public static PointCloudInfo LoadModel(double a = 3.0, double b = 2.0, double c = 1.5, int verticalRings = 15, int horizontalRings = 20, double distanceThreshold = -1.0)
    {
        var positions = new List<Point3D>();

        // 创建完整的椭球点网格
        var allPoints = new Point3D[verticalRings + 1, horizontalRings];

        // 生成所有点
        for (int v = 0; v <= verticalRings; v++)
        {
            double phi = Math.PI * v / verticalRings;
            double y = b * Math.Cos(phi);
            double currentRadius = Math.Sin(phi);

            for (int h = 0; h < horizontalRings; h++)
            {
                double theta = 2 * Math.PI * h / horizontalRings;
                double x = a * currentRadius * Math.Cos(theta);
                double z = c * currentRadius * Math.Sin(theta);
                allPoints[v, h] = new Point3D(x, y, z);
            }
        }

        // 收集满足条件的点(Y坐标<0且Z坐标>0)
        for (int v = 0; v <= verticalRings; v++)
        {
            for (int h = 0; h < horizontalRings; h++)
            {
                var point = allPoints[v, h];
                if (point.Y < 0 && point.Z > 0)
                {
                    positions.Add(point);
                }
            }
        }
        var pointCloudInfo = new PointCloudInfo()
        { 
           CameraInfo=new PointCloudCameraInfo() 
           {
               LookDirection = new Vector3D(0.671, -1.486, -86.403),
               UpDirection = new Vector3D(-0.005, -0.992, 0.018),
               Position = new Point3D(-0.029,-9.831,50.500)
           }
        
        };

        foreach (var point in positions)
        {
            Vector3D normal = new (
                 point.X / (a * a),
                 point.Y / (b * b),
                 point.Z / (c * c)
             );

            // 归一化法向量
            normal.Normalize();

            pointCloudInfo.ItemInfos.Add(new PointCloudItemInfo { Point = point, Vector = normal });
        }
        pointCloudInfo.RegionInfos.Add(new PointCloudRegionInfo { Index = 0, CenterPoint = new Point3D(0, -7.94, 9.18), DistanceThreshold = distanceThreshold });
        pointCloudInfo.RegionInfos.Add(new PointCloudRegionInfo { Index = 1, CenterPoint = new Point3D(0, -15.41, 6.37), DistanceThreshold = distanceThreshold });
        pointCloudInfo.RegionInfos.Add(new PointCloudRegionInfo { Index = 2, CenterPoint = new Point3D(7.42, -7.94, 5.39), DistanceThreshold = distanceThreshold });
        pointCloudInfo.RegionInfos.Add(new PointCloudRegionInfo { Index = 3, CenterPoint = new Point3D(-7.42, -7.94, 5.39), DistanceThreshold = distanceThreshold });

  

        // 将点分配到各个区域
        var assignedPoints = new HashSet<PointCloudItemInfo>();
        
        foreach (var regionInfo in pointCloudInfo.RegionInfos)
        {
            var regionPoints = new List<PointCloudRegionItemInfo>();
            
            // 找出距离该区域中心点在阈值内的所有点
            foreach (var pointInfo in pointCloudInfo.ItemInfos)
            {
                if (assignedPoints.Contains(pointInfo))
                    continue;
                    
                double dx = pointInfo.Point.X - regionInfo.CenterPoint.X;
                double dy = pointInfo.Point.Y - regionInfo.CenterPoint.Y;
                double dz = pointInfo.Point.Z - regionInfo.CenterPoint.Z;
                double distance = Math.Sqrt(dx * dx + dy * dy + dz * dz);
                
                if (distance <= distanceThreshold)
                {
                    var regionItemInfo = new PointCloudRegionItemInfo
                    {
                        Point = pointInfo.Point,
                        Vector = pointInfo.Vector,
                        DistanceToCenter = distance
                    };
                    
                    regionPoints.Add(regionItemInfo);
                    assignedPoints.Add(pointInfo);
                }
            }
            
            // 如果该区域有分配的点，找出距离中心点最近的点作为CenterItemInfo
            if (regionPoints.Count > 0)
            {
                var nearestPoint = regionPoints.OrderBy(p => p.DistanceToCenter).First();
                regionInfo.CenterItemInfo = nearestPoint;
                regionInfo.ItemInfos = regionPoints;
            }
        }
        
        // 从原始集合中移除已分配的点
        pointCloudInfo.ItemInfos.RemoveAll(x => assignedPoints.Contains(x));
        return pointCloudInfo;
    }

}
